package main

import (
	"sync"
	"fmt"
	"time"
)

type GoPool struct {
	numGo    int
	messages chan interface{}
	function func(interface{})
}

func New(numGoroutine int, function func(interface{})) *GoPool {
	return &GoPool{
		numGo:    numGoroutine,
		messages: make(chan interface{}),
		function: function,
	}
}

func (c *GoPool) Push(data interface{}) {
	c.messages <- data
}

func (c *GoPool) CloseQueue() {
	close(c.messages)
}

func (c *GoPool) Run() {
	var wg sync.WaitGroup

	wg.Add(c.numGo)

	for i := 0; i < c.numGo; i++ {
		go func() {
			for v := range c.messages {
				c.function(v)
			}
			wg.Done()
		}()
	}

	wg.Wait()
}

func main() {

	s := time.Now()
	numGoroutine := 1000
	taskCount := 1000000

	hp := New(numGoroutine, func(i interface{}) {
		fmt.Println(i.(int))
	})

	go func() {

		for i := 0; i < taskCount; i++ {
			hp.Push(i)
		}

		// push任务结束后必须关闭, 否则死锁
		hp.CloseQueue()
	}()

	// 跑起来! 伙计
	hp.Run()
	end := time.Now()
	fmt.Println(end.Sub(s))

}